/*
 * Copyright (c) 2011 Anthony Vandikas
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
 * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once

/**
 * Indicates which columns to show in a HistoryModel.
 */
enum HistoryDisplayFlag
{
	/**
	 * Don't show any columns.
	 */
	None = 0,

	/**
	 * Show a column containing the date the entry was recorded.
	 * This will show up as a date/time column when used in conjuction with the time column.
	 */
	DateColumn = 1,

	/**
	 * Show a column containing the time the entry was recorded.
	 * This will show up as a date/time column when used in conjuction with the date column.
	 */
	TimeColumn = 2,

	/**
	 * Show a column containing the student who recorded the entry.
	 */
	StudentColumn = 4,

	/**
	 * Show a column containing the item signed out by the student.
	 */
	ItemColumn = 8,
};

Q_DECLARE_FLAGS(HistoryDisplayFlags, HistoryDisplayFlag);
Q_DECLARE_OPERATORS_FOR_FLAGS(HistoryDisplayFlags);

class AbstractHistory;

/**
 * Provides a model for displaying the Entries in an AbstractHistory database.
 */
class HistoryModel : public QAbstractItemModel
{
	Q_OBJECT

	typedef QList<HistoryDisplayFlags> ColumnList;
	typedef QList<Entry> EntryList;

public:
	/**
	 * Constructs a new history model for the given database, showing the specified columns.
	 *
	 * @param history The history database to model.
	 * @param flags The columns to show.
	 */
	HistoryModel(AbstractHistory &history, HistoryDisplayFlags flags);

	/**
	 * Returns the index of the item in the model specified by the given row, column and parent index.
	 *
	 * @param row The item's row.
	 * @param column The item's column.
	 * @param parent The parent index.
	 */
	QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;

	/**
	 * Returns the parent of the model item with the given index, or an invalid index if none exist.
	 *
	 * @param child The child to query.
	 */
	QModelIndex parent(const QModelIndex &child) const override;

	/**
	 * Returns the number of rows.
	 *
	 * @param parent Not used.
	 */
	int rowCount(const QModelIndex &parent = QModelIndex()) const override;

	/**
	 * Returns the number of columns.
	 *
	 * @param parent Not used.
	 */
	int columnCount(const QModelIndex &parent = QModelIndex()) const override;

	/**
	 * Returns the data stored under the given role for the item referred to by the index.
	 *
	 * @param index The index to query.
	 * @param role The role of the data to retrieve.
	 */
	QVariant data(const QModelIndex &index, int role) const override;

	/**
	 * Returns the data for the given role and section in the header.
	 * 
	 * @param section The header to retrieve.
	 * @param orientation The orientation of the data.
	 * @param role The role of the data.
	 */
	QVariant headerData(int section, Qt::Orientation orientation, int role = 0) const override;

	/**
	 * Sorts the model by column in the given order.
	 * 
	 * @param column The column to sort by.
	 * @param order The order to sort by.
	 */
	void sort(int column, Qt::SortOrder order) override;

	/**
	 * Filters the shown items by the specified parameters.
	 *
	 * @param minDate The minimum date for the entries to have been entered.
	 * @param maxDate The maximum date for the entries to have been entered.
	 * @param studentKeywords The search terms for the student.
	 * @param itemKeywords The search terms for the item.
	 */
	void filter(
		const QDate &minDate,
		const QDate &maxDate, 
		const QStringList &studentKeywords, 
		const QStringList &itemKeywords);

private slots:
	/**
	 * Refreshes the model (retrieves a new set of entries from the underlying database).
	 */
	void refresh();

private:
	AbstractHistory *history;
	ColumnList columns;
	EntryList entries;

	std::function<bool (const Entry &left, const Entry &right)> sortComparisonFunc;

	QDate minDate, maxDate;
	QStringList studentKeywords, itemKeywords;
};

